package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.heima.api.feign.ApArticleFeignClient;
import com.heima.audit.baidu.BaiduImageScan;
import com.heima.audit.baidu.BaiduTextScan;
import com.heima.audit.tess4j.Tess4jClient;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmSensitiveMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.WmAutoScanService;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.tess4j.TesseractException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * TODO
 *
 * @Author mr.zhao
 * @Date 2025/6/22 16:45
 */
@Service
@Transactional
@Slf4j
public class WmAutoScanServiceImpl implements WmAutoScanService {
	@Autowired
	private WmNewsMapper wmNewsMapper;
	@Autowired
	private ApArticleFeignClient apArticleFeignClient;
	@Autowired
	private WmChannelMapper wmChannelMapper;
	@Autowired
	private WmUserMapper wmUserMapper;

	@Autowired
	private BaiduImageScan baiduImageScan;

	@Autowired
	private BaiduTextScan baiduTextScan;

	@Autowired
	private FileStorageService fileStorageService;

	@Autowired
	private Tess4jClient tess4jClient;

	/**
	 * 自动审核媒体文章
	 *
	 * @param id
	 */
	@Override
	@Async
	public void autoScanWmNews(Integer id) {
		//1. 查询自媒体文章
		WmNews wmNews = wmNewsMapper.selectById(id);
		if (wmNews == null){
			throw new RuntimeException("自媒体文章不存在");
		}
		if (wmNews.getStatus().equals(WmNews.Status.SUBMIT.getCode())){
			Map<String, List<String>> scanMaterialsList = extractImageAndContent(wmNews);
			//2. 调用百度云接口审核文本内容
			List<String> contentTexts = scanMaterialsList.get("contentTexts");
			//敏感词过滤
			boolean isSensitive= handleSensitiveWords(contentTexts,wmNews);
			Integer textConclusionType = null;
			for (String contentText : contentTexts) {
				//响应结果里conclusionType的四种可能值：1.合规，2.不合规，3.疑似，4.审核失败
				textConclusionType = baiduTextScan.textScan(contentText);
				if (textConclusionType != 1){
					return;
				}
			}
			//3, 调用百度云接口审核图片
			List<String> imagesUrls = scanMaterialsList.get("imagesUrls");
			Integer imageConclusionType = null;
			try {
				for (String imagesUrl : imagesUrls) {
					byte[] bytes = fileStorageService.downLoadFile(imagesUrl);
					//图片识别文字审核----begin----
					//从byte[]转换成butteredImage
					ByteArrayInputStream in = new ByteArrayInputStream(bytes);
					BufferedImage imageFile = ImageIO.read(in);
					//识别图片中的文字
					String result = tess4jClient.doOCR(imageFile);
					//审核是否包含自管理的敏感词
					boolean imageIsSensitive = handleSensitiveWords(Collections.singletonList(result), wmNews);
					if (!imageIsSensitive){
						return ;
					}
					//图片识别文字审核---end---

					imageConclusionType = baiduImageScan.imageScan(bytes);
					if (imageConclusionType != 1){
						return;
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			} catch (TesseractException e) {
				e.printStackTrace();
			}

			log.error("imageConclusionType: {}",imageConclusionType);
			if (textConclusionType == 1 && (imageConclusionType == 1 || imageConclusionType == null)){
				//审核通过
				wmNews.setStatus((short) 9);
				wmNews.setReason("审核通过");
			}

			//4.审核成功保存app端的相关文章数据
			ArticleDto dto=new ArticleDto();
			BeanUtils.copyProperties(wmNews,dto);
			//布局
			dto.setLayout(wmNews.getType());
			//频道
			dto.setChannelId(wmNews.getChannelId());
			//频道名称
			WmChannel wmChannel = wmChannelMapper.selectById(wmNews.getChannelId());
			if(wmChannel!=null){
				dto.setChannelName(wmChannel.getName());
			}
			//作者
			dto.setAuthorId(Long.valueOf(wmNews.getUserId()));
			//作者名称
			WmUser wmUser= wmUserMapper.selectById(wmNews.getUserId());
			if(wmUser!=null){
				dto.setAuthorName(wmUser.getName());
			}
			//设置文章id
			if(wmNews.getArticleId()!=null){
				dto.setId(wmNews.getArticleId());
			}
			dto.setCreatedTime(new Date());
			ResponseResult responseResult = apArticleFeignClient.save(dto);
			if (responseResult.getCode().equals(200)){
				//保存成功
				wmNews.setArticleId((Long) responseResult.getData());
				wmNewsMapper.updateById(wmNews);
			}else {
				//保存失败
				throw new RuntimeException("保存APP端文章失败");
			}
		}
	}

	@Autowired
	private WmSensitiveMapper wmSensitiveMapper;
	private boolean handleSensitiveWords(List<String> contentTexts, WmNews wmNews) {
		boolean isSensitive = true;
		//1. 获取所有敏感词
		List<WmSensitive> wmSensitiveList = wmSensitiveMapper.selectList(Wrappers.<WmSensitive>lambdaQuery().select(WmSensitive::getSensitives));
		List<String> collect = wmSensitiveList.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());
		//2. 初始化敏感库
		SensitiveWordUtil.initMap(collect);
		//3. 遍历文章内容查看是否包含敏感词
		for (String contentText : contentTexts) {
			Map<String, Integer> map = SensitiveWordUtil.matchWords(contentText);
			if (map.size()>0){
				//4. 包含敏感词,修改文章状态
				wmNews.setStatus((short) 2);
				wmNews.setReason("文章内容包含敏感词");
				wmNewsMapper.updateById(wmNews);
				isSensitive = false;
				break;
			}
		}
		return isSensitive;
	}

	/**
	 * 提取文本信息和图片信息
	 * @param wmNews
	 * @return
	 */
	private Map<String, List<String>> extractImageAndContent(WmNews wmNews) {
		//提取文章内容
		String content = wmNews.getContent();
		List<String> imagesUrls =new ArrayList<>();
		List<String> contentTexts =new ArrayList<>();
		Map<String,List<String>> scanMaterialsList =new HashMap<>();
		List<Map> maps = JSON.parseArray(content, Map.class);
		//提取文章图片
		for (Map map : maps) {
			if(map.get("type").equals("image")){
				String imgUrl = (String) map.get("value");
				imagesUrls.add(imgUrl);
			}
			if(map.get("type").equals("text")){
				String text = (String) map.get("value");
				contentTexts.add(text);
			}
		}
		scanMaterialsList.put("imagesUrls",imagesUrls);
		scanMaterialsList.put("contentTexts",contentTexts);
		return scanMaterialsList;
	}
}
